#include "../es.h"
#include "../es_log.h"
#include "../es_socket.h"
#include "../es_util.h"
#include "../extra/es_lua_json_handler.h"
#include <csignal>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <iostream>

#ifndef O_NONBLOCK
#define O_NONBLOCK 1
#endif

using namespace std;

class TestLogger : public esvr::Logger {
public:
  virtual void log(esvr::LogLevel level, const char *fmt, ...) override final {
    va_list args;
    printf("%s [%s] ", esvr::get_current_datetime_str().c_str(),
           esvr::LogLevelStr[level]);
    va_start(args, fmt);
    vfprintf(stdout, fmt, args);
    va_end(args);
    printf("\n");
  }
};

esvr::Logger *esvr::g_LoggerInst = new TestLogger;

static socket_t get_server_fd() {
  static socket_t server_fd = esvr::es_init_svr(NULL, 2048);
  return server_fd;
}

void close_server_fd() {
  // println("close socket");
  esvr::IOManager::instance().stop();
  esvr::es_close(get_server_fd());
  esvr::es_destroy_sock_module();
  if (esvr::g_LoggerInst) {
    delete esvr::g_LoggerInst;
    esvr::g_LoggerInst = NULL;
  }
}

void signal_func(int signal) {
  if (signal == SIGINT) {
    close_server_fd();
    exit(0);
  }
}

int main() {
  ::atexit(close_server_fd);
  signal(SIGINT, signal_func);
  esvr::es_init_sock_module();
  socket_t server_fd = get_server_fd();
  int len = 1;
  esvr::es_setopt(server_fd, SO_REUSEADDR, (void *)&len, sizeof(len));
  esvr::es_fcntl(server_fd, O_NONBLOCK, true);
  // println("Hello, World!");
  esvr::es_listen(server_fd);
  esvr::LuaJsonHandler ev;
  esvr::EventBus &bus = esvr::EventBus::get_instance();
  bus.add_handler<esvr::ConnectedEvent>(&ev);
  bus.add_handler<esvr::ClosedEvent>(&ev);
  bus.add_handler<esvr::ReadEvent>(&ev);
  bus.add_handler<esvr::WriteEvent>(&ev);
  esvr::IOManager::instance().start(server_fd);
  return 0;
}
